home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 101-125 / disk_108 / tek / xmodem.c < prev   
C/C++ Source or Header  |  1992-05-06  |  10KB  |  407 lines

  1. /*************************************************************
  2.  * vt100 terminal emulator - XMODEM protocol support
  3.  *
  4.  *    v2.6 870227 DBW - bug fixes for all the stuff in v2.5
  5.  *    v2.5 870214 DBW - more additions (see readme file)
  6.  *    v2.4 861214 DBW - lots of fixes/additions (see readme file)
  7.  *    v2.3 861101 DBW - minor bug fixes
  8.  *    v2.2 861012 DBW - more of the same
  9.  *    v2.1 860915 DBW - new features (see README)
  10.  *         860901 ACS - Added Parity and Word Length and support code
  11.  *         860823 DBW - Integrated and rewrote lots of code
  12.  *         860815 Steve Drew: readchar inproved with real timeouts
  13.  *    v2.0 860809 DBW - Major rewrite
  14.  *    v1.1 860720 DBW    - Switches, 80 cols, colors, bug fixes
  15.  *    v1.0 860712 DBW    - First version released
  16.  *
  17.  *************************************************************/
  18.  
  19. #include "vt100.h"
  20.  
  21. int enablexon = TRUE;
  22.  
  23. static unsigned long parity_settings[4] = {
  24.     0x96696996,
  25.     0x69969669,
  26.     0x69969669,
  27.     0x96696996 };
  28.  
  29. /************************************************************
  30. * Send a string (using sendchar below)
  31. ************************************************************/
  32.  
  33. void sendstring(s)
  34. char *s;
  35.     {
  36.     char c;
  37.  
  38.     while ((c = *s++) != '\000') sendchar(c);
  39.     }
  40.  
  41. /**************************************************************/
  42. /* send char and read char functions for the xmodem function */
  43. /************************************************************/
  44. void sendchar(ch)
  45. int ch;
  46.     {
  47.     int doxon,i,j,k;
  48.  
  49.     doxon = enablexon;
  50.     if (doxon) No_XON();
  51.     switch (p_parity) {
  52.     case 0:    /* no parity */
  53.     rs_out[0] = ch & 0xFF;
  54.     break;
  55.  
  56.     case 1: /* mark */
  57.     rs_out[0] = (ch & 0x7F) | 0x80;
  58.     break;
  59.  
  60.     case 2: /* space */
  61.     rs_out[0] = ch & 0x7F;
  62.     break;
  63.     
  64.     case 3:    /* even */
  65.     case 4: /* odd  */
  66.         i     = (ch >> 5) & 0x3;
  67.     j     = ch & 0x1F;
  68.     k     = ((parity_settings[i] >> j) & 0x1) << 7;
  69.     if (p_parity == 3)            /* even parity */
  70.         rs_out[0] = (ch & 0x7F) | k;
  71.     else                    /* odd parity */
  72.         rs_out[0] = (ch & 0x7F) | (k ^ 0x80);
  73.     }
  74.     DoIO(Write_Request);
  75.     if (doxon) Do_XON();
  76.     }
  77.  
  78. /* send a break to the host */
  79. void sendbreak() {
  80.     AbortIO(Read_Request);
  81.     Read_Request->IOSer.io_Command = SDCMD_BREAK;
  82.     DoIO(Read_Request);
  83.     Read_Request->IOSer.io_Command = CMD_READ;
  84.     SendIO(Read_Request);
  85.     }
  86.  
  87. int readchar()
  88.     {
  89.     int rd,ch;
  90.  
  91.     Timer.tr_time.tv_secs = ttime;
  92.     Timer.tr_time.tv_micro = 0;
  93.     SendIO((char *) &Timer.tr_node);
  94.     
  95.     rd = FALSE;
  96.     while (rd == FALSE)  
  97.         {    
  98.     Wait((1L << Read_Request->IOSer.io_Message.mn_ReplyPort->mp_SigBit) |
  99.             ( 1L << mywindow->UserPort->mp_SigBit) |
  100.             ( 1L << Timer_Port->mp_SigBit));
  101.     if (CheckIO(Read_Request))
  102.             {
  103.         WaitIO(Read_Request);
  104.         ch=rs_in[0];
  105.         rd = TRUE;
  106.         SendIO(Read_Request);
  107.         }
  108.     if (NewMessage=(struct IntuiMessage *)GetMsg(mywindow->UserPort)) {
  109.        if ((NewMessage->Class == RAWKEY) && (NewMessage->Code == 69))
  110.              {
  111.                  AbortIO((char *) &Timer);
  112.                  Wait (1L << Timer_Port->mp_SigBit);
  113.              req("ERROR:","User aborted transfer",0);
  114.              timeout = USERABORT;
  115.                  return('\0');
  116.              }
  117.             continue;
  118.             }
  119.         if (rd == FALSE && CheckIO(&Timer)) {
  120.             req("ERROR","Timeout waiting for character",0);
  121.             timeout = TIMEOUT;
  122.             return('\0');
  123.             }
  124.     }     /* end while */
  125.     AbortIO((char *) &Timer);
  126.     Wait (1L << Timer_Port->mp_SigBit);
  127.     timeout = GOODREAD;
  128.     return(ch & (p_parity == 0 ? 0xFF : 0x7F));
  129.     }
  130.  
  131. void No_XON() {
  132.  
  133.     /* turn off XON/XOFF processing */
  134.     enablexon = FALSE;
  135.     Write_Request->io_SerFlags |= SERF_XDISABLED;
  136.     Write_Request->IOSer.io_Command = SDCMD_SETPARAMS;
  137.     DoIO(Write_Request);
  138.     Write_Request->IOSer.io_Command = CMD_WRITE;
  139.     }
  140.  
  141. void Do_XON() {
  142.     /* turn on XON/XOFF processing */
  143.     enablexon = TRUE;
  144.     Write_Request->io_SerFlags &= ~SERF_XDISABLED;
  145.     Write_Request->IOSer.io_Command = SDCMD_SETPARAMS;
  146.     DoIO(Write_Request);
  147.     Write_Request->IOSer.io_Command = CMD_WRITE;
  148.     }
  149.  
  150. /**************************************/
  151. /* xmodem send and recieve functions */
  152. /************************************/
  153.  
  154. int XMODEM_Read_File(file)
  155. char *file;
  156.     {
  157.     int firstchar, sectnum, sectcurr, sectcomp, errors, errorflag;
  158.     unsigned int checksum, j, bufptr;
  159.     char scrstr[40],scrstr2[40];
  160.     bytes_xferred = 0L;
  161.     ttime = TTIME_SHORT;
  162.  
  163.     if ((fd = creat(file, 0)) < 0)
  164.     {
  165.     req("XMODEM Can't Open File:",file,0);
  166.     return FALSE;
  167.     }
  168.     else
  169.     strcpy(scrstr,"XMODEM Receive, <esc> to abort");
  170.     req(scrstr,"",0);
  171.  
  172.     sectnum = errors = bufptr = 0;
  173.     sendchar(NAK);
  174.     firstchar = 0;
  175.     No_XON();
  176.     while (firstchar != EOT && errors != ERRORMAX)
  177.     {
  178.     errorflag = FALSE;
  179.  
  180.     do {                                    /* get sync char */
  181.         firstchar = readchar();
  182.         if (timeout != GOODREAD) {
  183.         if (timeout == USERABORT || errors++ == ERRORMAX)
  184.             Do_XON();
  185.             return FALSE;
  186.         }
  187.         } while (firstchar != SOH && firstchar != EOT);
  188.  
  189.     if  (firstchar == SOH)
  190.         {
  191.         sprintf(scrstr2,"Getting Block %4d...",sectnum);
  192.         req(scrstr,scrstr2,0);
  193.         sectcurr = readchar();
  194.         if (timeout != GOODREAD) { Do_XON(); return FALSE; }
  195.         sectcomp = readchar();
  196.         if (timeout != GOODREAD) { Do_XON(); return FALSE; }
  197.         if ((sectcurr + sectcomp) == 255)
  198.         {
  199.         if (sectcurr == ((sectnum + 1) & 0xff))
  200.             {
  201.             checksum = 0;
  202.             for (j = bufptr; j < (bufptr + SECSIZ); j++)
  203.             {
  204.             bufr[j] = readchar();
  205.             if (timeout != GOODREAD) { Do_XON(); return FALSE; }
  206.             checksum = (checksum + bufr[j]) & 0xff;
  207.             }
  208.             if (checksum == readchar() && timeout == GOODREAD)
  209.             {
  210.             errors = 0;
  211.             sprintf(scrstr2,"Block %4d verified",sectnum);
  212.             sectnum++;
  213.             bufptr += SECSIZ;
  214.             bytes_xferred += SECSIZ;
  215.             req(scrstr,scrstr2,0);
  216.             if (bufptr == BufSize)
  217.                 {
  218.                 if (write(fd, bufr, BufSize-128) == EOF)
  219.                 {
  220.                 req(scrstr,"Error Writing File",0);
  221.                 Do_XON();
  222.                 return FALSE;
  223.                 }
  224.                 bufptr = 128;
  225.                 for (j = 0; j < 128; j++)
  226.                 bufr[j] = bufr[(BufSize-128)+j];
  227.                 }
  228.             sendchar(ACK);
  229.             }
  230.             else
  231.             {
  232.             errorflag = TRUE;
  233.             if (timeout == USERABORT) { Do_XON(); return FALSE; }
  234.             }
  235.             }
  236.         else
  237.             {
  238.             /* got a duplicate sector */    
  239.             if (sectcurr == (sectnum & 0xff))
  240.             {
  241.             /* wait until we time out for 5secs */
  242.             do {
  243.                 readchar();
  244.                 } while (timeout == GOODREAD);
  245.             if (timeout == USERABORT) {
  246.                 Do_XON();
  247.                 return FALSE;
  248.                 }
  249.             req(scrstr,"Received Duplicate Sector",0);
  250.             sendchar(ACK);
  251.             }
  252.             else errorflag = TRUE;
  253.                 }
  254.         }
  255.         else errorflag = TRUE;
  256.         }
  257.     if (errorflag == TRUE)
  258.         {
  259.         errors++;
  260.         req(scrstr,"Error",0);
  261.         sendchar(NAK);
  262.         }
  263.     }        /* end while */
  264.     if ((firstchar == EOT) && (errors < ERRORMAX))
  265.     {
  266.     sendchar(ACK);
  267.     while (bufptr > 0 && (bufr[--bufptr] == 0x00 ||
  268.                   bufr[bufptr]   == 0x1A)) ;
  269.     write(fd, bufr, ++bufptr);
  270.     close(fd);
  271.     Do_XON();
  272.     return TRUE;
  273.     }
  274.     Do_XON();
  275.     return FALSE;
  276.     }
  277.  
  278. int XMODEM_Send_File(file)
  279. char *file;
  280.     {
  281.     int sectnum, bytes_to_send, size, attempts, c;
  282.     unsigned checksum, j, bufptr;
  283.     char scrstr[40],scrstr2[40];
  284.     bytes_xferred = 0;
  285.     ttime = TTIME_LONG;
  286.  
  287.     if ((fd = open(file, 0)) < 0) {
  288.     req("XMODEM","Cannot Open Send File",0);
  289.     return FALSE;
  290.     }
  291.     else
  292.     strcpy(scrstr,"XMODEM Send, <esc> to abort");
  293.     req(scrstr,"",0);
  294.     attempts = 0;
  295.     sectnum = 1;
  296.     No_XON();
  297.     /* wait for sync char */
  298.     j=1;
  299.     while (((c = readchar()) != NAK) && (j++ < ERRORMAX))
  300.     if (timeout == USERABORT) { Do_XON(); return(FALSE); }
  301.     if (j >= (ERRORMAX))
  302.     {
  303.     req(scrstr,"Receiver not sending NAKs",0);
  304.     Do_XON();
  305.     return FALSE;
  306.     }
  307.  
  308.     while ((bytes_to_send = read(fd, bufr, BufSize)) && 
  309.         attempts != RETRYMAX)
  310.     {
  311.     if (bytes_to_send == EOF)
  312.         {
  313.         req(scrstr,"Error Reading File",0);
  314.         Do_XON();
  315.         return FALSE;
  316.         }
  317.  
  318.     bufptr = 0;
  319.     while (bytes_to_send > 0 && attempts != RETRYMAX)
  320.         {
  321.         attempts = 0;
  322.         sprintf(scrstr2,"Sending block %4d",sectnum);
  323.         do {
  324.         req(scrstr,scrstr2,0);
  325.         sendchar(SOH);
  326.         sendchar(sectnum);
  327.         sendchar(~sectnum);
  328.         checksum = 0;
  329.         size = SECSIZ <= bytes_to_send ? SECSIZ : bytes_to_send;
  330.         bytes_to_send -= size;
  331.         for (j = bufptr; j < (bufptr + SECSIZ); j++)
  332.         if (j < (bufptr + size)) {
  333.             sendchar(bufr[j]);
  334.             checksum += bufr[j];
  335.             }
  336.         else sendchar(0);
  337.         sendchar(checksum);
  338.         attempts++;
  339.         c = readchar();
  340.         if (timeout == USERABORT) {
  341.             req(scrstr,"ABORTED",0);
  342.             Do_XON();
  343.             return FALSE;
  344.             }
  345.         } while ((c != ACK) && (attempts != RETRYMAX));
  346.         bufptr += size;
  347.         bytes_xferred += size;
  348.         sprintf(scrstr2,"Sent block %4d",sectnum);
  349.         req(scrstr,scrstr2,0);
  350.         sectnum++;
  351.         }
  352.     }
  353.     close(fd);
  354.     if (attempts == RETRYMAX)
  355.     {
  356.     req(scrstr,"No Acknowledgment, ABORTING",0);
  357.     Do_XON();
  358.     return FALSE;
  359.     }
  360.     else
  361.     {
  362.     attempts = 0;
  363.     do {
  364.         sendchar(EOT);
  365.         attempts++;
  366.         } while ((readchar() != ACK) &&
  367.              (attempts != RETRYMAX) &&
  368.              (timeout != USERABORT)) ;
  369.     if (attempts == RETRYMAX)
  370.         req(scrstr,"NO END OF FILE",0);
  371.     }
  372.     Do_XON();
  373.     return TRUE;
  374.     }
  375.  
  376. /* allow for multi file xfers separated by commas under
  377.     kermit and XMODEM */
  378.  
  379. void multi_xfer(name,mode,do_send)
  380. char *name;
  381. int (*mode)();
  382. int do_send;
  383.     {
  384.     int done = 0;
  385.     int status;
  386.     char *p;
  387.     
  388.     if (name[0] == '$' && name[1] == '\0') {
  389.     saybye();
  390.     return;
  391.     }
  392.     p = name;
  393.     while(*p == ' ') p++;
  394.     while(*p && *p != ',' && *p != ' ') p++;
  395.     if (*p == '\0')   done = TRUE;
  396.     else          multi = 1;
  397.     *p = '\0';
  398.  
  399.     status = ((*mode)(name, multi));
  400.     if (status == FALSE) close(fd);
  401.     if (!done && timeout != USERABORT) multi_xfer(++p, mode, do_send);
  402.     else emit('\n');
  403.     server = 0;
  404.     multi = 0;
  405.     }
  406.  
  407.